package multistate;

/**
 * 赛车比赛类，用于演示多态。
 */
public class RaceModel {
    /**
     * 同一个类的两个对象两两比赛模式
     */
//    public void race(Car a1, Car a2) {
//        a1.move();
//        a2.move();
//    }

    /**
     * 两种不同的交通工具进行比赛
     */
//    public void race(Car a1, Bike a2) {
//        a1.move();
//        a2.move();
//    }
//    // 重载一个方法，解决不同类型对象的接入问题！
//    public void race(Car a1, MotoBike a2) {
//        a1.move();
//        a2.move();
//    }

    //    public void race(Bike a1, MotoBike a2) {
//        a1.move();
//        a2.move();
//    }
    // 重载方法在这里解决的是新增类型的问题——扩展性问题！
    // 优势：能解决扩展性问题
    // 弊端：1.每增加一种新类型，就要扩展n-1个方法！！导致方法膨胀，极难维护！
    // 2.无法预测未来的变更！！！
    // 一个良好的程序设计评判标准：能否应付未来的需求变化（扩展）
    // 面向对象程序设计的6大设计原则就是用来指导如何良好设计的
    // 其中之一就是开闭原则，也是它们的总纲！——对扩展开发，对修改关闭。
    // 需要一种一劳永逸的解决方案：向上转型！即动态多态——不同类的对象调用相同方法，产生的不同响应。
    // 实现的条件：1.类之间必须存在上下级关系（继承或者实现接口）——向上转型的前提
    // 2.必须要重写同名方法（比如这里的move）——实现不同响应的前提
    // 3.还需要调用这个同名方法
    // 4.必须要向上转型——将子类对象绑定到父类引用上——实现良好扩展的关键步骤！
    //      直接方式：父类类型 父类引用 = 子类实例;
    //      间接方式：
    //          方法设计：方法名(父类类型  父类引用){   …   }
    //          方法调用：方法名(子类的对象);
    public void race(Moveable a1, Moveable a2) {
        a1.move();
        a2.move();
    }

    /**
     * 新增了一种交通工具，如果要实现两两比赛，得怎么做？
     */
    public static void main(String[] args) {
        RaceModel raceModel = new RaceModel();
        // 课堂练习：模仿代码，设计一个小汽车和公交车比赛的示例
        Car car1 = new Car("大黄蜂");
        Bike bike1 = new Bike("自行赛车");
        System.out.println("---第一轮---");
        raceModel.race(car1, bike1);
        MotoBike motoBike1 = new MotoBike("极地摩托");
        // 方法调用根据参数个数和类型来判定
        System.out.println("---第2轮---");
        raceModel.race(car1, motoBike1);
        System.out.println("---第3轮---");
        raceModel.race(bike1, motoBike1);
        System.out.println("---第4轮---");
        Bus bus1 = new Bus("357路公交车");
        raceModel.race(bike1, bus1);
        raceModel.race(motoBike1, bus1);
        raceModel.race(car1, bus1);
    }
}
